package ihttp

import (
	"embed"
	"gitee.com/go-boot/boot-interfaces/ilogger"
	"io"
	"mime/multipart"
	"net/http"
	"reflect"
	"time"
)

type (
	HandlerFunc func(ctx IHttpContext)

	HandlersChain []HandlerFunc

	// ICookie cookie设置
	ICookie interface {
		SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)
		Cookie(name string) (string, error)
	}

	// IHttpResponse 返回数据
	IHttpResponse interface {
		Response() http.ResponseWriter
		Headers(map[string]string) // 设置多个Header头
		Header(key string, value string)
		Json(code int, data any)
		File(header map[string]string, source io.Reader)
		Status(code int) // 状态
	}

	// IParam 参数 /user/:id
	IParam interface {
		DefaultParam(key string, value string)
		ParamString(key string) (value string, err error)
		ParamInt(key string) (value int, err error)
		ParamInt8(key string) (value int8, err error)
		ParamInt32(key string) (value int32, err error)
		ParamInt64(key string) (value int64, err error)
		ParamFloat32(key string) (value float32, err error)
		ParamFloat64(key string) (value float64, err error)
		ParamBool(key string) (value bool, err error)
		ParamJson(obj any) error
	}

	// IQuery 请求 /path?id=1234&name=Manu&value=
	IQuery interface {
		DefaultQuery(key string, value string)
		QueryString(key string) (value string, err error)
		QueryInt(key string) (value int, err error)
		QueryInt8(key string) (value int8, err error)
		QueryInt32(key string) (value int32, err error)
		QueryInt64(key string) (value int64, err error)
		QueryFloat32(key string) (value float32, err error)
		QueryFloat64(key string) (value float64, err error)
		QueryBool(key string) (value bool, err error)
		QueryTime(key string) (value time.Time, err error)
		QueryJson(obj any) error
	}

	IBody interface {
		PostForm(key string) (value string, err error)
		PostFormNumber(key string) (value int, err error)
		PostFormFile(key string) (value *multipart.FileHeader, err error)
		PostFormArray(key string) (value []string, err error)
		PostJson(obj any) error
	}

	// IBodyBind 绑定
	IBodyBind interface {
		Name() string
		Bind(req *http.Request, obj any) error
	}

	// IValidator 验证器
	IValidator interface {
		Verify(obj any) error
	}

	// IValidField 验证器抽象逻辑
	IValidField interface {
		Top() reflect.Value                                                                                      // 返回顶层结构体
		Parent() reflect.Value                                                                                   // 返回当前字段的父结构体
		Field() reflect.Value                                                                                    // 返回当前用于验证的字段
		FieldName() string                                                                                       // 返回带有标签名的字段名，标签名优先于字段的实际名字
		StructFieldName() string                                                                                 // 返回结构体字段的名称，即字段在结构体中的实际名称
		Param() string                                                                                           // 返回用于验证当前字段的参数
		GetTag() string                                                                                          // 返回当前验证标签的名称
		ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)                 // 获取字段值的实际底层类型
		GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool)                                            // 遍历父结构体以检索由参数中提供的命名空间表示的特定字段
		GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) // 类似于 GetStructFieldOK2()，但接受父结构体以开始查找字段和命名空间，为验证器提供更多的灵活性
	}

	// IHttpRequest 请求数据
	IHttpRequest interface {
		Request() *http.Request
		Query() IQuery
		Param() IParam
		SetParam(IRouterParams)
		Body() IBody
		GetHeader(key string) string
		Path() string
		SetPath(path string)
		Method() string
		RemoteIp() string    // 获取IP
		ClientIp() string    // 客户端IP
		ContentType() string // 请求头
	}

	// IHttpContext 上下文
	IHttpContext interface {
		Build(response http.ResponseWriter, request *http.Request) IHttpContext

		Log() ilogger.ILogger

		Body() IBody
		Query() IQuery
		Param() IParam

		Request() IHttpRequest
		Response() IHttpResponse

		Path() string   // 路径
		Method() string // 请求方法
		Set(key string, value any)
		Get(key string) (any, bool)

		File(filepath string) // 文件
	}

	// IRouterInterceptor 拦截器
	IRouterInterceptor interface {
		Order() int
		Name() string
		Before(ctx IHttpContext) bool // 执行之前
		After(ctx IHttpContext) bool  // 执行之后
	}

	// IRouter 路由
	IRouter interface {
		Push(routers ...IRouter) IRouter // 添加路由
		Parent(parent IRouter) IRouter

		Handler(method string) (HandlerFunc, bool)
		Children() []IRouter
		Path() string
		Methods() []string
		IsEnd() bool

		Router(method string, handler HandlerFunc) IRouter
		Head(handler HandlerFunc) IRouter
		Get(handler HandlerFunc) IRouter
		Post(handler HandlerFunc) IRouter
		Delete(handler HandlerFunc) IRouter
		Put(handler HandlerFunc) IRouter
		Patch(handler HandlerFunc) IRouter
		Options(handler HandlerFunc) IRouter
		Any(handler HandlerFunc) IRouter
	}

	// IRouterTree 路由树
	IRouterTree interface {
		Match(ctx IHttpContext) HandlerFunc
	}

	IRouterParam interface {
		Key() string
		Value() string
		Set(string, string) IRouterParam
	}

	IRouterParams interface {
		Get(string) (string, bool)
		Set(string, string)
	}

	// IServer server
	IServer interface {
		Start(handlers ...func())
		Interceptor(interceptor ...IRouterInterceptor)
		Routes(basePath ...string) IRouter
		StaticEmbed(urlPath string, filepath string, embed embed.FS)
	}
)
